﻿using AlgoritmoConstrutivo.entidades;
using AlgoritmoConstrutivo.leitor;
using AlgoritmoConstrutivo.particionamento;
using Entidades;
using RandomKeyGenerator;
using Support;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AlgoritmoConstrutivo
{
    public class Program
    {
        static Grafo software1;
        static Particionador part = new Particionador();
        static InstanceReader instance_r = new InstanceReader();
        static Orquestrador2 orq2;
        public static Stopwatch timerTotal = new Stopwatch();
        public static String FOLDER = @"C:\Mestrado\geracao_1000_100\Temp";
        public static int POPULACAO = 100;
        public static double tempoTotalGeracao;
        public static int MEDIA = 20;
        public static DirectoryInfo initialFolder;
        public static DirectoryInfo instanciaFolder;

        static List<Configuration2> generateConfigs(List<Configuration2> cfgs)
       {
           if (cfgs.Count!=0)
            cfgs = new List<Configuration2>();
           
         
            ConfiguracaoFactory cf = new ConfiguracaoFactory();
            LinkedList<ListaConfiguracoes> lCfg = new LinkedList<ListaConfiguracoes>();
            cf.inicializar(lCfg);

            List<Double> configuracao = new List<Double>();

            cf.GenerateAllConfigs(lCfg.First, configuracao);

            cf.ConvertToRealConfigsCombinado(cfgs);

            int i = 0;
            foreach (Configuration2 cfg in cfgs)
            {
                Console.WriteLine( "Configuracao:" + i + " " + cfg +Environment.NewLine);
                i++;

            }

            return cfgs;

       }


       static void PrintGraphics(List<Estatistica> stats, String decoder, String instancia)
        {

          IOrderedEnumerable<Estatistica> ordEst =  stats.OrderBy(x => x.Geracao);

            string nomeArquivo = decoder + "_" + DateTime.Now.Ticks.ToString() + "_grafico_" +instancia+ ".txt";
            File.AppendAllText(FOLDER + nomeArquivo, "\n");


            Estatistica maiorMQDiferente = new Estatistica(-1,-1);
      
            foreach (Estatistica est in ordEst)
            {
                if (est.Mq > maiorMQDiferente.Mq)
                {
                    maiorMQDiferente = est;
                    String a = est.Geracao + ";" + est.Mq + ";" + est.Mutante + ";" + est.Elite + Environment.NewLine;

                    File.AppendAllText(FOLDER + nomeArquivo, a);
                }

            }


        }



        static void Main(string[] args)
        {
            List<EstatisticaConsolidado> stats = null;

            List<FileInfo> files = new List<FileInfo>();
            List<Configuration2> configs = new List<Configuration2>();
            initialFolder = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\" + DateTime.Now.Ticks.ToString()); //setando a raiz.


            DirectoryInfo instancias = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Mestrado\\temp");

            //DirectoryInfo instancias = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Mestrado\\Instancias Finais\\Medias\\i2");

            DirectoryInfo instDefault = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Mestrado\\Instancias Finais");


            FileInfo cfgsPorInstancia = new FileInfo(initialFolder + "\\instanciasCfg.csv");
          
            if (!initialFolder.Exists) //criei a pasta raiz com o nome das inssstâncias.
                initialFolder.Create();

            File.AppendAllText(cfgsPorInstancia.FullName, "INSTANCIA;CFGS" + Environment.NewLine);

           String decoder = "clustersPorVizinho.ClustersPorVizinhosDinamico";
            string nomeArquivo = decoder + "_" + DateTime.Now.Ticks.ToString() + ".txt";




            String[] allFiles = Directory.GetFiles(instancias.FullName);


           Output.turnLogs = true;

           //já possuo uma lista de filesInfos com todos os paths dos arquivos a serem trabalhados.
           for (int i = 0; i < allFiles.Length; i++)
           {
               files.Add(new FileInfo(allFiles[i]));
               instance_r.ReadFile(new FileInfo(allFiles[i]));
           }

           //gera o txt com as tabelas divididas por pequena, média e grande.
           instance_r.GenerateTableWithInstances(initialFolder, instDefault);


           configs = generateConfigs(configs);

            foreach (FileInfo fi in files) //para cada instância
            {   
                if (!fi.Exists)
                {
                    Output.WriteInformation("O arquivo " + fi.Name + "não existe");
                    continue;
                }

                instanciaFolder = new DirectoryInfo(initialFolder.FullName + "\\" + fi.Name);
                FileInfo resumoInstanciaFile = new FileInfo(initialFolder.FullName + "\\" + fi.Name + "_resumo_media.csv");

                if (!instanciaFolder.Exists) //criei a pasta raiz com o nome das instâncias.
                    instanciaFolder.Create();


                Output.WriteInformation("O processo será executado em " + files.Count + " instâncias");
                Output.WriteInformation("Teremos " + MEDIA + " execuções com "+configs.Count+ " configurações" );
                Output.WriteInformation("Vai ser iniciada a geração para " + fi.Name + " com" + nomeArquivo);

                List<Grafo> softwares = new List<Grafo>(POPULACAO);


                softwares.Add(new Grafo(fi.Name));

                softwares[0] = instance_r.ReadFile(fi);

           
                POPULACAO = (int)Math.Round(Math.Log(Double.Parse(softwares[0].RetornarNumNos().ToString()),2) * 20);

              
                foreach (Configuration2 cfg in configs)
                    cfg.Population = POPULACAO;


                for (int k = 1; k < POPULACAO; k++)
                {
                 
                    softwares.Add(new Grafo(fi.Name));
                    softwares[k] = instance_r.ReadFile(fi);
                }

               
                Program.orq2 = new Orquestrador2(softwares[0].RetornarNumNos(), softwares, "Algoritmos." + decoder, POPULACAO, null, configs);

  
                stats = orq2.IniciarGeracoes();
            
                String resulFinal =  fi.Name + ";";

                foreach (EstatisticaConsolidado est in stats)
                    resulFinal+= est.IdCfg + ";";

                resulFinal += Environment.NewLine;
           
                File.AppendAllText(cfgsPorInstancia.FullName, resulFinal);

             
            }

           Console.ReadKey();
        }


    }
}
